{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from elasticsearch7 import Elasticsearch\n",
    "from elasticsearch_dsl import Document, Date, Nested, Boolean, \\\n",
    "    analyzer, InnerDoc, Completion, Keyword, Text\n",
    "from datetime import datetime"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [],
   "source": [
    "html_strip = analyzer('html_strip',\n",
    "    tokenizer=\"standard\",\n",
    "    filter=[\"standard\", \"lowercase\", \"stop\", \"snowball\"],\n",
    "    char_filter=[\"html_strip\"]\n",
    ")"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [],
   "source": [
    "class Comment(InnerDoc):\n",
    "    author = Text(fields={'raw': Keyword()})\n",
    "    content = Text()\n",
    "    created_at = Date()\n",
    "\n",
    "    def age(self):\n",
    "        return datetime.now() - self.created_at\n",
    "\n",
    "class Post(Document):\n",
    "    title = Text()\n",
    "    title_suggest = Completion()\n",
    "    created_at = Date()\n",
    "    published = Boolean()\n",
    "    category = Text(\n",
    "        fields={'raw': Keyword()}\n",
    "    )\n",
    "\n",
    "    comments = Nested(Comment)\n",
    "\n",
    "    class Index:\n",
    "        name = 'blog'\n",
    "\n",
    "    def add_comment(self, author, content):\n",
    "        self.comments.append(\n",
    "          Comment(author=author, content=content, created_at=datetime.now()))\n",
    "\n",
    "    def save(self, ** kwargs):\n",
    "        self.created_at = datetime.now()\n",
    "        return super().save(** kwargs)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "outputs": [],
   "source": [
    "es_client = Elasticsearch(host=\"127.0.0.1\", port=9200, timeout=200)\n",
    "Post.init(using=es_client)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [
    {
     "data": {
      "text/plain": "<Elasticsearch([{}])>"
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "es_client\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [
    {
     "ename": "KeyError",
     "evalue": "\"There is no connection with alias 'default'.\"",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mKeyError\u001B[0m                                  Traceback (most recent call last)",
      "\u001B[1;32md:\\python\\python3.9\\lib\\site-packages\\elasticsearch_dsl\\connections.py\u001B[0m in \u001B[0;36mget_connection\u001B[1;34m(self, alias)\u001B[0m\n\u001B[0;32m    109\u001B[0m         \u001B[1;32mtry\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 110\u001B[1;33m             \u001B[1;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mcreate_connection\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0malias\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m**\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_kwargs\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0malias\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m    111\u001B[0m         \u001B[1;32mexcept\u001B[0m \u001B[0mKeyError\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;31mKeyError\u001B[0m: 'default'",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001B[1;31mKeyError\u001B[0m                                  Traceback (most recent call last)",
      "\u001B[1;32m<ipython-input-22-806b329e61dd>\u001B[0m in \u001B[0;36m<module>\u001B[1;34m\u001B[0m\n\u001B[1;32m----> 1\u001B[1;33m \u001B[0mPost\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0minit\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m",
      "\u001B[1;32md:\\python\\python3.9\\lib\\site-packages\\elasticsearch_dsl\\document.py\u001B[0m in \u001B[0;36minit\u001B[1;34m(cls, index, using)\u001B[0m\n\u001B[0;32m    154\u001B[0m         \u001B[1;32mif\u001B[0m \u001B[0mindex\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    155\u001B[0m             \u001B[0mi\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mi\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mclone\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mname\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mindex\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 156\u001B[1;33m         \u001B[0mi\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0msave\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0musing\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0musing\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m    157\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    158\u001B[0m     \u001B[1;32mdef\u001B[0m \u001B[0m_get_index\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mindex\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;32mNone\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mrequired\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;32mTrue\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;32md:\\python\\python3.9\\lib\\site-packages\\elasticsearch_dsl\\index.py\u001B[0m in \u001B[0;36msave\u001B[1;34m(self, using)\u001B[0m\n\u001B[0;32m    296\u001B[0m         \u001B[0mfail\u001B[0m \u001B[1;32mwith\u001B[0m \u001B[0mthe\u001B[0m \u001B[0munderlying\u001B[0m \u001B[0mexception\u001B[0m\u001B[1;33m.\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    297\u001B[0m         \"\"\"\n\u001B[1;32m--> 298\u001B[1;33m         \u001B[1;32mif\u001B[0m \u001B[1;32mnot\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mexists\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0musing\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0musing\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m    299\u001B[0m             \u001B[1;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mcreate\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0musing\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0musing\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    300\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;32md:\\python\\python3.9\\lib\\site-packages\\elasticsearch_dsl\\index.py\u001B[0m in \u001B[0;36mexists\u001B[1;34m(self, using, **kwargs)\u001B[0m\n\u001B[0;32m    412\u001B[0m         \u001B[0;31m`\u001B[0m\u001B[0;31m`\u001B[0m\u001B[0mElasticsearch\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mindices\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mexists\u001B[0m\u001B[0;31m`\u001B[0m\u001B[0;31m`\u001B[0m \u001B[0munchanged\u001B[0m\u001B[1;33m.\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    413\u001B[0m         \"\"\"\n\u001B[1;32m--> 414\u001B[1;33m         \u001B[1;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_get_connection\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0musing\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mindices\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mexists\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mindex\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_name\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m**\u001B[0m\u001B[0mkwargs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m    415\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    416\u001B[0m     \u001B[1;32mdef\u001B[0m \u001B[0mexists_type\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0musing\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;32mNone\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m**\u001B[0m\u001B[0mkwargs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;32md:\\python\\python3.9\\lib\\site-packages\\elasticsearch_dsl\\index.py\u001B[0m in \u001B[0;36m_get_connection\u001B[1;34m(self, using)\u001B[0m\n\u001B[0;32m    133\u001B[0m         \u001B[1;32mif\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_name\u001B[0m \u001B[1;32mis\u001B[0m \u001B[1;32mNone\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    134\u001B[0m             \u001B[1;32mraise\u001B[0m \u001B[0mValueError\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;34m\"You cannot perform API calls on the default index.\"\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 135\u001B[1;33m         \u001B[1;32mreturn\u001B[0m \u001B[0mget_connection\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0musing\u001B[0m \u001B[1;32mor\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_using\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m    136\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    137\u001B[0m     \u001B[0mconnection\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mproperty\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0m_get_connection\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;32md:\\python\\python3.9\\lib\\site-packages\\elasticsearch_dsl\\connections.py\u001B[0m in \u001B[0;36mget_connection\u001B[1;34m(self, alias)\u001B[0m\n\u001B[0;32m    111\u001B[0m         \u001B[1;32mexcept\u001B[0m \u001B[0mKeyError\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    112\u001B[0m             \u001B[1;31m# no connection and no kwargs to set one up\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 113\u001B[1;33m             \u001B[1;32mraise\u001B[0m \u001B[0mKeyError\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;34m\"There is no connection with alias %r.\"\u001B[0m \u001B[1;33m%\u001B[0m \u001B[0malias\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m    114\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    115\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;31mKeyError\u001B[0m: \"There is no connection with alias 'default'.\""
     ]
    }
   ],
   "source": [
    "Post.init()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "outputs": [
    {
     "data": {
      "text/plain": "'created'"
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first = Post(title='My First Blog Post, yay!', published=True)\n",
    "# assign some field values, can be values or lists of values\n",
    "first.category = ['everything', 'nothing']\n",
    "# every document has an id in meta\n",
    "first.meta.id = 47\n",
    "\n",
    "\n",
    "# save the document into the cluster\n",
    "first.save(using=es_client)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "outputs": [
    {
     "data": {
      "text/plain": "'created'"
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "second = Post(\n",
    "    title='Second Day, Yes!',\n",
    "    published=True,\n",
    "    category='something'\n",
    ")\n",
    "second.save(using=es_client)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "outputs": [
    {
     "data": {
      "text/plain": "{'_id': '47',\n '_index': 'blog',\n '_source': {'title': 'My First Blog Post, yay!',\n  'published': True,\n  'category': ['everything', 'nothing'],\n  'created_at': datetime.datetime(2021, 2, 6, 1, 14, 49, 128791)}}"
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first.to_dict(include_meta=True)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}